#    Copyright 2012 New Mexico EPSCoR
#
#    This file is part of Teacher's P.E.T.
#
#    Teacher's P.E.T. is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Teacher's P.E.T. is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Teacher's P.E.T..  If not, see <http://www.gnu.org/licenses/>.
from django.db import models
from django import forms
from django.shortcuts import Http404
from django.template.defaultfilters import slugify

from tags.templatetags.sanitize import sanitize
from apps.additions import AllowAdditions

import logging
import datetime

logger = logging.getLogger('pet.apps.course.models')

def get_course_path(instance, filename):
    filename_pieces = filename.rsplit('.')
    name = filename_pieces[0]
    ext = ''
    if len(filename_pieces) > 1: ext = '.'.join(filename_pieces[1:])
    ret_string = "%s/%s" % (instance.course_id, slugify(name))
    if ext: ret_string += ".%s" % ext
    return ret_string
    
class Course(models.Model):
    """
    This represents a single course
    """
    course_id = models.CharField(max_length=255, unique=True)
    course_title = models.CharField(max_length=255)
    course_subtitle = models.CharField(max_length=255,blank=True,null=True)
    course_description = models.TextField(blank=True,null=True)
    course_css = models.FileField(upload_to=get_course_path, blank=True, null=True)
    course_js = models.FileField(upload_to=get_course_path, blank=True, null=True)
    course_favicon = models.FileField(upload_to=get_course_path, blank=True, null=True)
    show_until = models.DateTimeField(blank=True,null=True,help_text="(Optional) After this date & time, the class website will not be available")
    accessible_until = models.DateTimeField(blank=True,null=True,help_text="(Optional) After this date/time, students can no longer access their information for this class")
    
    #Course-wide Options    
    show_class_roster = models.BooleanField("Show Class Roster",default=True,help_text="If true, allows the class to see each other's profiles via a link in the main menu")
    class_roster_title = models.CharField("Class Roster Title",max_length=50,default="Class",help_text="The title to give the class roster in the menu")
    
    #Participant Options
    show_students_by_name = models.BooleanField("Show Students By Name",default=True,help_text="If True, shows student listing to instructor by name, otherwise it will use the student id")
    allow_student_avatar_change = models.BooleanField("Allow Student Avatar Change",default=False,help_text="If True, allows the students to upload their own avatars")
    show_student_avatars = models.BooleanField("Show Student Avatars",default=True,help_text="If True, this allows student avatars to be visible to other students")
    allow_students_to_email_others = models.BooleanField("Allow Student Email",default=False,help_text="If True, this allows students to email each other through the website(no email addresses are shown)")
    allow_student_name_and_email_change = models.BooleanField("Allow Student Name and Email Change",default=True,help_text="If True, students will be able to edit their own names and email addresses on their profiles")

    #Gradebook options
    anonymous_grading_default = models.BooleanField("Default to Anonymous Grading", default=True, help_text="If true, grading will be done without student names shown (can be toggled while grading)")
    display_grade_metrics = models.BooleanField(default=False,help_text="When students are viewing their individual grades, should they see metrics (Min, Max, Avg, Median) for the entire class?")

    #Activity Options
    activity_title = models.CharField("Activity Title",default="Activity",max_length=50)
    activity_title_plural = models.CharField("Activity Title (plural)",default="Activities",max_length=50)
    default_time_due = models.TimeField("Default Due Time",default=datetime.time(23,59,59),help_text="This is the default time assignments are set to be due if no time is given")
    default_submissions_allowed = models.PositiveIntegerField("Default Submissions Allowed",default=10,help_text="""This is the default number of repeat submissions
                                                                  allowed for a student to make on any given activity (this can be overridden on an activity-by-activity basis)""")

    # Event Options
    event_calendar_percent = models.FloatField("Event Calendar Size",default=66.66,help_text="This is the size (as a percent) that the event calendar should take on the course homepage")
    event_calendar_show_time_due = models.BooleanField("Show time due on Event Calendar",default=True,help_text="If true, assignments will show the time they are due in the event calendar")
 
    def save(self, *args, **kwargs):
        self.course_id = sanitize(self.course_id)
        self.course_title = sanitize(self.course_title)
        if self.course_subtitle: self.course_subtitle = sanitize(self.course_subtitle)
        if self.course_description: self.course_description = sanitize(self.course_description)
        super(Course,self).save(*args,**kwargs)
    def __unicode__(self):
        from options import Options
        if Options.get_option("Show Courses by Title",True):
            return self.course_title
        else: return self.course_id
    @staticmethod
    def find(course_id):
        if not course_id: course_id = '__default'
        TheCourse = Course.objects.filter(course_id=course_id)
        if not TheCourse and course_id == '__default':
            from options import Options
            TheCourse = Course(course_id='__default',course_title=Options.get_option("Default Course Title","Teacher's P.E.T."),course_subtitle=Options.get_option("Default Course Subtitle","Pedagagoical Enhancement Tool"))
            TheCourse.save()
            return TheCourse
        if TheCourse: return TheCourse[0]
        return None
    @staticmethod
    def find_or_404(course_id):
        Result = Course.find(course_id)
        if not Result:
            logger.http404('Course %s not found',course_id,display_caller=True)
            raise Http404
        return Result
    @staticmethod
    def RequestCourse(request):
        path = request.path
        if 'SCRIPT_NAME' in request.META and path.startswith(request.META['SCRIPT_NAME']):
            path = path.replace(request.META['SCRIPT_NAME'],"")
        path = path.lstrip('/')
        course_id, sep, after = path.partition('/')
        TheCourse = Course.objects.filter(course_id=course_id)
        if not TheCourse:
            TheCourse = Course.objects.filter(course_id='__default')
        return TheCourse[0] if TheCourse else None
AllowAdditions(Course)

class CourseEditForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(CourseEditForm,self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance and instance.id and instance.course_id == '__default':
            self.fields['course_id'].widget.attrs['disabled'] = True
            self.fields['course_id'].required = False
    def clean(self):
        if self.instance.course_id == '__default':
            self.cleaned_data['course_id'] = self.instance.course_id
        return super(CourseEditForm,self).clean()
    class Meta:
        model = Course
        
class CourseForm(forms.ModelForm):
    course = forms.MultipleChoiceField(choices=(), required=False)
    def __init__(self, *args, **kwargs):
        allow_none = False
        if 'allow_none' in kwargs:
            allow_none = kwargs.pop('allow_none') == True
        if 'course' in kwargs:
            course = kwargs.pop('course')
            if course or allow_none:
                if 'initial' in kwargs and not 'course' in kwargs['initial']:
                    kwargs['initial']['course'] = [course] if course else ['None']
                elif course and 'initial' in kwargs and 'course' in kwargs['initial']:
                    Courses = kwargs['initial']['course'].split(',')
                    Courses.append(course)
                    kwargs['initial']['course'] = ','.join(Courses)
                elif not 'initial' in kwargs:
                    kwargs['initial'] = {'course':[course] if course else ['None']}
        if 'courses' in kwargs:
            courses = kwargs.pop('courses')
            if courses or allow_none:
                if 'initial' in kwargs and not 'course' in kwargs['initial']:
                    kwargs['initial']['course'] = courses.split(',') if courses else ['None']
                elif courses and 'initial' in kwargs and 'course' in kwargs['initial']:
                    Courses = kwargs['initial']['course'].split(',')
                    Courses.extend(courses.split(','))
                    kwargs['initial']['course'] = ','.join(Courses)
                elif not 'initial' in kwargs:
                    kwargs['initial'] = {'course':courses.split(',') if courses else ['None']}
        if 'instance' in kwargs and kwargs['instance']:
            if 'initial' in kwargs:
                kwargs['initial']['course'] = kwargs['instance'].course.split(',') if kwargs['instance'].course else ['None']
            else:
                kwargs['initial'] = {'course':kwargs['instance'].course.split(',') if kwargs['instance'].course else ['None']}
        if not 'initial' in kwargs:
            kwargs['initial'] = {}
        if not 'course' in kwargs['initial'] and allow_none:
            kwargs['initial']['course'] = ['None']
        super(CourseForm,self).__init__(*args, **kwargs)
        COURSE_CHOICES = tuple([(course.course_id,course.course_id) for course in Course.objects.all()])
        if allow_none: COURSE_CHOICES = (('None','None'),) + COURSE_CHOICES
        self.fields['course'].choices = COURSE_CHOICES
    def clean_course(self):
        course = self.cleaned_data.get("course")
        if 'None' in course: course.remove('None')
        return ",".join(course)
    class Meta:
        abstract = True